{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Daytona SDK Examples"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Load the Daytona SDK and create a sandbox"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import base64\n",
    "import io\n",
    "import os\n",
    "from pprint import pp\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from daytona import (\n",
    "    BarChart,\n",
    "    CompositeChart,\n",
    "    CreateSandboxFromImageParams,\n",
    "    Daytona,\n",
    "    Image,\n",
    "    LineChart,\n",
    "    SessionExecuteRequest,\n",
    ")\n",
    "\n",
    "daytona = Daytona()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sandbox = daytona.create(\n",
    "    CreateSandboxFromImageParams(\n",
    "        image=(\n",
    "            Image.base(\"python:3.13.4-bookworm\")\n",
    "            .run_commands(\n",
    "                \"apt-get update && apt-get install -y nodejs npm\",\n",
    "                \"npm install -g typescript typescript-language-server\",\n",
    "            )\n",
    "            .pip_install(\"matplotlib\")\n",
    "        ),\n",
    "    ),\n",
    "    timeout=200,\n",
    "    on_snapshot_create_logs=print,\n",
    ")\n",
    "\n",
    "print(sandbox.id)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Code and Command Execution\n",
    "\n",
    "### Code Execution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "response = sandbox.process.code_run('print(\"Hello World!\")')\n",
    "if response.exit_code != 0:\n",
    "    print(f\"Error: {response.exit_code} {response.result}\")\n",
    "else:\n",
    "    print(response.result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Command Execution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "response = sandbox.process.exec('echo \"Hello World from exec!\"', timeout=10)\n",
    "if response.exit_code != 0:\n",
    "    print(f\"Error: {response.exit_code} {response.result}\")\n",
    "else:\n",
    "    print(response.result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exec Sessions\n",
    "\n",
    "Sessions can be used to execute multiple commands in a single shell that preserves context between commands."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "exec_session_id = \"exec-session-1\"\n",
    "sandbox.process.create_session(exec_session_id)\n",
    "session = sandbox.process.get_session(exec_session_id)\n",
    "pp(session)\n",
    "print()\n",
    "\n",
    "# Execute the first command in the session\n",
    "execCommand1 = sandbox.process.execute_session_command(exec_session_id, SessionExecuteRequest(command=\"export FOO=BAR\"))\n",
    "if execCommand1.exit_code != 0:\n",
    "    print(f\"Error: {execCommand1.exit_code} {execCommand1.output}\")\n",
    "\n",
    "# Get the command details\n",
    "session_command = sandbox.process.get_session_command(exec_session_id, execCommand1.cmd_id)\n",
    "pp(session_command)\n",
    "print()\n",
    "\n",
    "# Execute a second command in the session and see that the environment variable is set\n",
    "execCommand2 = sandbox.process.execute_session_command(exec_session_id, SessionExecuteRequest(command=\"echo $FOO\"))\n",
    "if execCommand2.exit_code != 0:\n",
    "    print(f\"Error: {execCommand2.exit_code} {execCommand2.output}\")\n",
    "else:\n",
    "    print(f\"Output: {execCommand2.output}\\n\")\n",
    "\n",
    "logs = sandbox.process.get_session_command_logs(exec_session_id, execCommand2.cmd_id)\n",
    "print(f\"Logs stdout: {logs.stdout}\")\n",
    "print(f\"Logs stderr: {logs.stderr}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Charts\n",
    "\n",
    "Daytona automatically detects any plot creations while running remote code and saves them in `response.artifacts.charts`. This feature is available only for **Matplotlib** plots."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "code = \"\"\"\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Data\n",
    "categories = ['A', 'B', 'C', 'D']\n",
    "values = [20, 35, 30, 10]\n",
    "\n",
    "# Plot\n",
    "plt.figure(figsize=(8, 5))\n",
    "plt.bar(categories, values, color='skyblue', edgecolor='black')\n",
    "\n",
    "# Labels and title\n",
    "plt.xlabel('Category')\n",
    "plt.ylabel('Value')\n",
    "plt.title('Bar Chart Example')\n",
    "\n",
    "plt.grid(axis='y', linestyle='--', alpha=0.7)\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\"\"\"\n",
    "\n",
    "response = sandbox.process.code_run(code)\n",
    "chart = response.artifacts.charts[0]\n",
    "\n",
    "img_data = base64.b64decode(chart.png)\n",
    "img = plt.imread(io.BytesIO(img_data))\n",
    "plt.imshow(img)\n",
    "plt.axis(\"off\")\n",
    "plt.show()\n",
    "\n",
    "print(f\"type: {chart.type}\")\n",
    "print(f\"title: {chart.title}\")\n",
    "if isinstance(chart, BarChart):\n",
    "    print(f\"x_label: {chart.x_label}\")\n",
    "    print(f\"y_label: {chart.y_label}\")\n",
    "    print(\"elements:\")\n",
    "    for element in chart.elements:\n",
    "        print(f\"\\n\\tlabel: {element.label}\")\n",
    "        print(f\"\\tgroup: {element.group}\")\n",
    "        print(f\"\\tvalue: {element.value}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Composite Charts\n",
    "All subplots are included as individual `Chart` instances within the `elements` list of a parent `Chart` of type `CompositeChart`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "code = \"\"\"\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "# Data for bar chart\n",
    "categories = ['A', 'B', 'C', 'D']\n",
    "bar_values = [20, 35, 30, 10]\n",
    "\n",
    "# Data for line chart\n",
    "x = np.linspace(0, 10, 100)\n",
    "y1 = np.sin(x)\n",
    "y2 = np.cos(x)\n",
    "y3 = np.tan(x) * 0.1  # scaled to fit nicely\n",
    "\n",
    "# Create a figure with 2 subplots\n",
    "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))\n",
    "\n",
    "# --- Bar Chart (subplot 1) ---\n",
    "ax1.bar(categories, bar_values, color='skyblue', edgecolor='black')\n",
    "ax1.set_title('Bar Chart')\n",
    "ax1.set_xlabel('Category')\n",
    "ax1.set_ylabel('Value')\n",
    "ax1.grid(axis='y', linestyle='--', alpha=0.7)\n",
    "\n",
    "# --- Line Chart with 3 lines (subplot 2) ---\n",
    "ax2.plot(x, y1, label='sin(x)', linewidth=2)\n",
    "ax2.plot(x, y2, label='cos(x)', linewidth=2)\n",
    "ax2.plot(x, y3, label='0.1 * tan(x)', linewidth=2)\n",
    "ax2.set_title('Line Chart with 3 Lines')\n",
    "ax2.set_xlabel('X-axis')\n",
    "ax2.set_ylabel('Y-axis')\n",
    "ax2.grid(True, linestyle='--', alpha=0.7)\n",
    "ax2.legend()\n",
    "\n",
    "# Add main title\n",
    "fig.suptitle('Composite Chart Example', fontsize=16)\n",
    "\n",
    "# Adjust layout and show\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\"\"\"\n",
    "\n",
    "response = sandbox.process.code_run(code)\n",
    "chart = response.artifacts.charts[0]\n",
    "\n",
    "img_data = base64.b64decode(chart.png)\n",
    "img = plt.imread(io.BytesIO(img_data))\n",
    "plt.imshow(img)\n",
    "plt.axis(\"off\")\n",
    "plt.show()\n",
    "\n",
    "print(f\"type: {chart.type}\")\n",
    "print(f\"title: {chart.title}\")\n",
    "if isinstance(chart, CompositeChart):\n",
    "    for subplot in chart.elements:\n",
    "        print(f\"\\n\\ttype: {subplot.type}\")\n",
    "        print(f\"\\ttitle: {subplot.title}\")\n",
    "        if isinstance(subplot, BarChart):\n",
    "            print(f\"\\tx_label: {subplot.x_label}\")\n",
    "            print(f\"\\ty_label: {subplot.y_label}\")\n",
    "            print(\"\\telements:\")\n",
    "            for element in subplot.elements:\n",
    "                print(f\"\\n\\t\\tlabel: {element.label}\")\n",
    "                print(f\"\\t\\tgroup: {element.group}\")\n",
    "                print(f\"\\t\\tvalue: {element.value}\")\n",
    "        elif isinstance(subplot, LineChart):\n",
    "            print(f\"\\tx_label: {subplot.x_label}\")\n",
    "            print(f\"\\ty_label: {subplot.y_label}\")\n",
    "            print(f\"\\tx_ticks: {subplot.x_ticks}\")\n",
    "            print(f\"\\tx_tick_labels: {subplot.x_tick_labels}\")\n",
    "            print(f\"\\tx_scale: {subplot.x_scale}\")\n",
    "            print(f\"\\ty_ticks: {subplot.y_ticks}\")\n",
    "            print(f\"\\ty_tick_labels: {subplot.y_tick_labels}\")\n",
    "            print(f\"\\ty_scale: {subplot.y_scale}\")\n",
    "            print(\"\\telements:\")\n",
    "            for element in subplot.elements:\n",
    "                print(f\"\\n\\t\\tlabel: {element.label}\")\n",
    "                print(f\"\\t\\tpoints: {element.points}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## File System\n",
    "\n",
    "- List Files\n",
    "- Create Folder\n",
    "- Upload File\n",
    "- Download File\n",
    "- Replace in Files\n",
    "- Search Files\n",
    "- Get File Info\n",
    "- Move Files\n",
    "- Delete File\n",
    "- Set File Permissions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# List files in the sandbox\n",
    "files = sandbox.fs.list_files(\".\")\n",
    "pp(files)\n",
    "\n",
    "# Create a new directory in the sandbox\n",
    "new_dir = \"new-dir\"\n",
    "sandbox.fs.create_folder(new_dir, \"755\")\n",
    "\n",
    "file_path = os.path.join(new_dir, \"data.txt\")\n",
    "\n",
    "# Add a new file to the sandbox\n",
    "file_content = b\"Hello, World!\"\n",
    "sandbox.fs.upload_file(file_content, file_path)\n",
    "\n",
    "# Search for the file we just added\n",
    "matches = sandbox.fs.find_files(\".\", \"World!\")\n",
    "pp(matches)\n",
    "\n",
    "# Replace the contents of the file\n",
    "sandbox.fs.replace_in_files([file_path], \"Hello, World!\", \"Goodbye, World!\")\n",
    "\n",
    "# Read the file\n",
    "downloaded_file = sandbox.fs.download_file(file_path)\n",
    "print(\"File content:\", downloaded_file.decode(\"utf-8\"))\n",
    "\n",
    "# Change the file permissions\n",
    "sandbox.fs.set_file_permissions(file_path, mode=\"777\")\n",
    "\n",
    "# Get file info\n",
    "file_info = sandbox.fs.get_file_info(file_path)\n",
    "pp(file_info)  # Should show the new permissions\n",
    "\n",
    "# Move the file to the new location\n",
    "new_file_path = \"moved-data.txt\"\n",
    "sandbox.fs.move_files(file_path, new_file_path)\n",
    "\n",
    "# Find the file in the new location\n",
    "search_results = sandbox.fs.search_files(\".\", \"moved-data.txt\")\n",
    "pp(search_results)\n",
    "\n",
    "# Delete the file\n",
    "sandbox.fs.delete_file(new_file_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Git\n",
    "\n",
    "- Clone Repository\n",
    "- Pull Repository\n",
    "- List Branches\n",
    "- Delete a Branch\n",
    "- Create a Branch\n",
    "- Checkout a Branch\n",
    "- Git Log\n",
    "- Git Status\n",
    "- Git Add\n",
    "- Git Commit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "project_dir = \"learn-typescript\"\n",
    "\n",
    "# Clone the repository\n",
    "sandbox.git.clone(\"https://github.com/panaverse/learn-typescript\", project_dir, \"master\")\n",
    "\n",
    "sandbox.git.pull(project_dir)\n",
    "\n",
    "branches = sandbox.git.branches(project_dir)\n",
    "pp(branches)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## LSP\n",
    "\n",
    "- Start Language Server\n",
    "- Notify Language Server of Document Change\n",
    "- Get Completions\n",
    "- Document Symbols\n",
    "- Workspace Symbols"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "project_dir = \"learn-typescript\"\n",
    "\n",
    "# Search for the file we want to work on\n",
    "matches = sandbox.fs.find_files(project_dir, \"var obj1 = new Base();\")\n",
    "print(\"Matches:\", matches)\n",
    "\n",
    "# Start the language server\n",
    "lsp = sandbox.create_lsp_server(\"typescript\", project_dir)\n",
    "lsp.start()\n",
    "\n",
    "# Notify the language server of the document we want to work on\n",
    "lsp.did_open(matches[0].file)\n",
    "\n",
    "# Get symbols in the document\n",
    "symbols = lsp.document_symbols(matches[0].file)\n",
    "print(\"Symbols:\", symbols)\n",
    "\n",
    "# Fix the error in the document\n",
    "sandbox.fs.replace_in_files([matches[0].file], \"var obj1 = new Base();\", \"var obj1 = new E();\")\n",
    "\n",
    "# Notify the language server of the document change\n",
    "lsp.did_close(matches[0].file)\n",
    "lsp.did_open(matches[0].file)\n",
    "\n",
    "# Get completions at a specific position\n",
    "completions = lsp.completions(matches[0].file, {\"line\": 12, \"character\": 18})\n",
    "print(\"Completions:\", completions)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sandbox Management\n",
    "\n",
    "- List Sandboxes\n",
    "- Stop Sandbox\n",
    "- Start Sandbox\n",
    "- Remove Sandbox"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = daytona.list()\n",
    "print(f\"Total sandboxes count: {result.total}\")\n",
    "\n",
    "for sandbox in result.items:\n",
    "    print(f\"Sandbox ID: {sandbox.id}, State: {sandbox.state}\")\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "daytona.stop(sandbox)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "daytona.start(sandbox)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "daytona.delete(sandbox)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
